<template>
  <el-card class="box-card">
    <div class="search">
      <el-input v-if="isValueExists('role-getrolepage')" v-model="listQuery.searchString"
        placeholder="请输入关键字" style="width: 400px;" />
      <el-button v-if="isValueExists('role-getrolepage')" class="button" :icon="Search"
        type="primary" @click.prevent="roleQuery">查询</el-button>
      <el-button v-if="isValueExists('role-addrole')" class="button" :icon="Plus"
        @click.prevent="addInfo">新增</el-button>
    </div>

    <el-table :data="tableData" stripe style="width: 100%">
      <el-table-column prop="roleId" label="ID" />
      <el-table-column prop="roleName" label="角色名" />
      <el-table-column prop="status" label="状态">
        <template #default="{ row }">
          <el-tag :type="tagFilter(row.status)">
            {{ StatusType(row.status) }}
          </el-tag>
        </template>
      </el-table-column>
      <el-table-column fixed="right" width="150">
        <template #default="{ row }">
          <div>
            <el-button v-if="isValueExists('role-modifyrole')" link type="primary" size="small"
              @click.prevent="editInfo(row.roleId)">编辑</el-button>
            <el-button v-if="isValueExists('role-removerole')" link type="danger" size="small"
              @click="removeInfo(row.roleId)">删除</el-button>
          </div>
          <div>
            <el-button link type="success" size="small" @click="AssignRole(row.roleId)">用户</el-button>
            <el-button v-if="isValueExists('role-setrolemenus')" link type="warning" size="small"
              @click="AssignMenu(row.roleId)">菜单</el-button>
            <el-button v-if="isValueExists('role-blockedrole')" link type="info" size="small"
              @click="freezeInfo(row.roleId)">
              {{ row.status == -1 ? '解冻' : '冻结' }}
            </el-button>
          </div>
        </template>
      </el-table-column>
    </el-table>
    <!-- 分页 -->
    <div class="pagination">
      <el-pagination background layout="prev, pager, next, sizes" :total="totalUserCount" :hide-on-single-page="isHide"
        @size-change="handleSizeChange" @current-change="handleCurrentChange" />
    </div>
  </el-card>

  <!-- 角色编辑 -->
  <el-dialog v-model="dialogVisible" :title="modifyWindowTitle" width="30%" :before-close="handleClose">
    <el-form ref="ruleFormRef" :model="roleInfo" :rules="rules" label-width="80px">
      <el-form-item label="角色名称" prop="roleName">
        <el-input v-model="roleInfo.roleName" />
      </el-form-item>
      <el-form-item label="是否启用">
        <el-switch v-model="roleInfo.status" />
      </el-form-item>
      <el-form-item label="所有用户">
        <el-switch v-model="roleInfo.setAll" />
      </el-form-item>
    </el-form>
    <template #footer>
      <span class="dialog-footer">
        <el-button @click="dialogVisible = false">取消</el-button>
        <el-button type="primary" @click="submit(ruleFormRef)">确定</el-button>
      </span>
    </template>
  </el-dialog>

  <!-- 角色分配 -->
  <el-dialog v-model="userDialogVisible" title="角色分配" width="30%" :before-close="userHandleClose">
    <div class="search">
      <el-input v-model="userListQuery.searchString" placeholder="请输入关键字" style="width: 200px;" />
      <el-button class="button" :icon="Search" type="primary" @click.prevent="AssignRole(currentRoleId)">查询</el-button>
    </div>
    <el-table ref="multipleTableRef" stripe :data="userData.arr" style="width: 100%"
      @selection-change="handleSelectionChange" :row-key="getRowKeys">
      <el-table-column type="selection" style="width: 55px;" :reserve-selection="true" />
      <el-table-column prop="name" label="姓名" />
      <el-table-column prop="sex" label="性别">
        <template #default="{ row }">
          <el-tag :type="row.sex == 0 ? '' : row.sex == 1 ? 'warning' : 'danger'">
            {{ sexFilter(row.sex) }}
          </el-tag>
        </template>
      </el-table-column>
      <el-table-column prop="status" label="状态">
        <template #default="{ row }">
          <el-tag :type="tagFilter(row.status)">
            {{ StatusType(row.status) }}
          </el-tag>
        </template>
      </el-table-column>
    </el-table>
    <!-- 分页 -->
    <div class="pagination">
      <el-pagination background layout="prev, pager, next, sizes" :total="totalUserCount"
        :hide-on-single-page="userData.arr.length === 0" @size-change="userHandleSizeChange"
        @current-change="userHandleCurrentChange" />
    </div>
    <template #footer>
      <span class="dialog-footer">
        <el-button @click="userRoleCancel">取消</el-button>
        <el-button type="primary" @click="userRoleSubmit()">确定</el-button>
      </span>
    </template>
  </el-dialog>

  <!-- 菜单分配 -->
  <el-dialog v-model="menuDialogVisible" title="菜单分配" width="30%" :before-close="menuHandleClose">
    <el-tree :data="dataTreeList.value" :props="{
      label: 'menuText',
      children: 'childMenus'
    }" show-checkbox @check-change="handleCheckChange" node-key="id" empty-text="暂无数据" check-on-click-node="true"
      highlight-current="true" :expand-on-click-node="false" ref="menuMultipleTableRef"
      :default-checked-keys='selectTreeArray.value'>
      <template #default="{ node, data }">
        <el-icon>
          <component :is="InitIcon(data.icon)"></component>
        </el-icon>
        <span>{{ node.label }}</span>
      </template>
    </el-tree>
    <template #footer>
      <span class="dialog-footer">
        <el-button @click="roleMenuCancel">取消</el-button>
        <el-button type="primary" @click="roleMenuSubmit">确定</el-button>
      </span>
    </template>
  </el-dialog>
</template>

<style scoped>
.avatar-uploader .avatar {
  width: 50px;
  height: 50px;
  display: block;
}

.avatar-uploader .el-upload {
  border: 1px dashed var(--el-border-color);
  border-radius: 6px;
  cursor: pointer;
  position: relative;
  overflow: hidden;
  transition: var(--el-transition-duration-fast);
}

.avatar-uploader .el-upload:hover {
  border-color: var(--el-color-primary);
}

.el-icon.avatar-uploader-icon {
  font-size: 28px;
  color: #8c939d;
  width: 50px;
  height: 50px;
  text-align: center;
}
</style>

<script setup>
import { ref, onMounted, computed, reactive, markRaw, nextTick, onBeforeMount } from 'vue'
import axios from '@/api'
import { defUrl } from '@/api/index'
import { ElMessage, ElMessageBox, alertProps } from 'element-plus'
import { InitIcon, IconSource, StatusType, currentMenuPermission } from '@/common'
import { useRouter } from "vue-router";
import {
  Search,
  Plus,
  Delete
} from "@element-plus/icons-vue";

const tableData = ref([]);
let totalCount = ref(0);
const isHide = ref(false);
const listQuery = reactive({
  pageIndex: 1,
  pageSize: 10,
  searchString: ''
});
const dialogVisible = ref(false)
let roleInfo = reactive({
  roleId: 0,
  roleName: '',
  status: 0,
  setAll: false
});
const ruleFormRef = ref();
const isModify = ref(true);
const oldRole = ref({});
let modifyWindowTitle = ref('新增');
const userDialogVisible = ref(false);
const currentRoleId = ref(0);
const userData = reactive({ arr: [] });
const multiSelection = reactive({ arr: [] });
const totalUserCount = ref(0);
const userListQuery = reactive({
  pageIndex: 1,
  pageSize: 10,
  searchString: ''
});
const multipleTableRef = ref()
const roleUser = reactive({ roleId: 0, users: [] });
const menuDialogVisible = ref(false); //分配菜单弹窗是否显示
const assignMenuRoleId = ref(0); //被分配菜单的角色ID
const selectTreeArray = reactive([]); //被选中的菜单ID
const checkedArray = reactive([]);
const dataTreeList = reactive([]);
const menuTotalCount = ref(0);
const menuMultipleTableRef = ref();
const btnArray = reactive([]);

const getRowKeys = (row) => {
  //记录每行key值
  return row.userId;
}

const getMenuRowKeys = (row) => {
  return row.menuId;
}

//#region 表单校验
const checkRoleName = async (rule, value, callback) => {
  const { data } = await axios.get(`role/${roleInfo.roleId}/${roleInfo.roleName}/${isModify.value}`);
  console.log(data);

  const { data: d, success, message } = data;
  if (!success) {
    callback(new Error(message));
  }

  if (d) {
    callback(new Error("角色名已存在"));
  }

  callback();
}

const rules = reactive({
  roleName: [
    {
      required: true,
      message: '请输入角色名',
      trigger: 'blur'
    },
    {
      validator: checkRoleName,
      trigger: 'blur'
    }
  ]
});
//#endregion

//#region 格式化文本

const tagFilter = computed(() => item => {
  switch (item) {
    case 1:
      return 'success';
    case 0:
      return 'info'
    case -1:
      return 'warning'
    default:
      return 'danger'
  }
})

const sexFilter = computed(() => item => {
  switch (item) {
    case 0:
      return '男';
    case 1:
      return '女';
    default:
      return item;
  }
})

const menuTypeFilter = computed(() => item => {
  switch (item) {
    case 0:
      return '菜单'
    case 1:
      return '按钮'
  }
});

//#endregion

//#region 方法
//钩子函数

onBeforeMount(() => {
  var menuId = useRouter().currentRoute.value.meta.id;
  btnArray.value = currentMenuPermission(menuId);
})

onMounted(async () => {
  keydownEvent();
  roleQuery();

})

const keydownEvent = () => {
  document.onkeydown = (e) => {
    if (e.defaultPrevented) {
      return;
    }

    const body = document.getElementsByTagName('body')[0];
    if (e.key === 'Enter') {
      roleQuery();
    }
  }
}

//角色查询
const roleQuery = async () => {
  //向后端发送请求，获取用户数据
  let url = `Role/${listQuery.pageIndex}/${listQuery.pageSize}/${listQuery.searchString}`;
  let { data } = await axios.get(url);
  console.log(data);

  let { data: d, success, message } = data;

  if (success) {
    // 表格数据
    tableData.value = d.dataList;
    totalCount.value = d.recordCount;
  } else {
    ElMessage({
      type: "warning",
      message: message
    });
  }
}

//角色新增
const addInfo = async () => {
  isModify.value = false;
  modifyWindowTitle.value = '新增'

  if (ruleFormRef.value !== undefined) {
    ruleFormRef.value.resetFields();
  }

  dialogVisible.value = true;
}

//角色编辑
const editInfo = async (id) => {
  isModify.value = true;
  modifyWindowTitle.value = '编辑'

  if (ruleFormRef.value !== undefined) {
    ruleFormRef.value.resetFields();
  }

  let { data } = await axios.get(`Role/${id}`);
  console.log(data);

  let { data: d, success, message } = data;
  if (!success) {
    ElMessage({
      type: 'error',
      message: message
    });

    return;
  }

  oldRole.value = d;

  roleInfo.roleId = d.roleId;
  roleInfo.roleName = d.roleName;
  roleInfo.status = d.status == 1;

  dialogVisible.value = true;
}

//角色删除
const removeInfo = async (id) => {
  ElMessageBox.confirm('是否删除？', '提醒', {
    type: 'warning',
    icon: markRaw(Delete)
  })
    .then(async () => {
      let { data } = await axios.delete(`/role/${id}`);
      let { success, message } = data;

      if (success) {
        ElMessage({
          type: "success",
          message: "删除成功"
        });

        await roleQuery();
      } else {
        ElMessage({
          type: "warning",
          message: message
        });
      }
    })
    .catch(() => {
      ElMessage({
        type: "warning",
        message: '操作已取消'
      });
    })
}

//角色冻结
const freezeInfo = async (id) => {
  ElMessageBox.confirm('是否冻结/解冻？', '提醒', {
    type: 'warning',
    icon: markRaw(Delete)
  })
    .then(async () => {
      let { data } = await axios.put(`/role/blocked/${id}`);
      let { success, message } = data;

      if (success) {
        ElMessage({
          type: "success",
          message: "冻结/解冻成功"
        });

        await roleQuery();
      } else {
        ElMessage({
          type: "warning",
          message: message
        });
      }
    })
    .catch(() => {
      ElMessage({
        type: "warning",
        message: '操作已取消'
      });
    });
}

//提交
const submit = async (formEl) => {
  if (!formEl) return
  //校验
  await formEl.validate(async (valid, fields) => {
    if (!valid) {
      ElMessage({
        type: 'warning',
        message: '验证失败，请正确输入信息后再提交'
      });

      return;
    }

    roleInfo.status = roleInfo.status ? 1 : 0;
    console.log(roleInfo);

    let roleId = ref(0);
    if (isModify.value) {
      let { data } = await axios.put('role', roleInfo);
      let { data: d, success, message } = data;

      roleId.value = roleInfo.roleId;

      if (!success) {
        ElMessage({
          type: 'error',
          message: message
        });

        return;
      }
    } else {
      let { data } = await axios.post('role', roleInfo);
      let { data: d, success, message } = data;

      roleId.value = d.roleId;

      if (!success) {
        ElMessage({
          type: 'error',
          message: message
        });

        return;
      }
    }

    if (roleInfo.setAll === true) {
      let { data } = await axios.post(`UserRole/${roleId.value}`);
      let { data: d, success: s, message: m } = data;

      if (!s) {
        ElMessage({
          type: 'warning',
          message: m
        });
      } else {
        ElMessage({
          type: 'success',
          message: '保存成功'
        });
      }
    }

    dialogVisible.value = false;

    await roleQuery();
  })
}

//切换页大小
const handleSizeChange = (val) => {
  listQuery.pageSize = val;
  roleQuery();
}

//翻页
const handleCurrentChange = (val) => {
  listQuery.pageIndex = val;
  roleQuery();
}

//窗体关闭
const closeWindow = () => {
  dialogVisible.value = false;
}

//窗体关闭
const handleClose = (done) => {
  done();
}

//用户窗体关闭
const userHandleClose = (done) => {
  multipleTableRef.value.clearSelection();
  userListQuery.searchString = "";

  done();
}

const menuHandleClose = (done) => {
  done();
}

//查询
async function userQuery() {
  //向后端发送请求，获取用户数据
  let url = `User/${userListQuery.pageIndex}/${userListQuery.pageSize}/${userListQuery.searchString}`;
  let { data } = await axios.get(url);

  let { data: d, success, message } = data;

  if (success) {
    // 表格数据
    userData.arr = d.dataList;
    totalUserCount.value = d.recordCount;
  } else {
    ElMessage({
      type: 'warning',
      message: message
    })
  }
}

//用户角色批量分配
const AssignRole = async (roleId) => {
  if (roleId !== NaN && roleId !== undefined) {
    currentRoleId.value = parseInt(roleId);
  }

  userDialogVisible.value = true;

  await userQuery();

  if (!multiSelection.arr) {
    multipleTableRef.value.clearSelection();
    return;
  }

  let { data } = await axios.get(`UserRole/${currentRoleId.value}`);
  let { data: d, success, message } = data;
  if (!success) {
    ElMessage({
      type: 'warning',
      message: message
    });

    return;
  }

  if (!d) {
    return;
  }

  multiSelection.arr = d;

  multipleTableRef.value.clearSelection();

  multiSelection.arr.forEach((row) => {
    let index = userData.arr.findIndex(u => u.userId === row.userId);
    let user = userData.arr[index];

    if (user !== undefined) {
      multipleTableRef.value.toggleRowSelection(user, true);
    }
  });
}

//提交角色分配
const userRoleSubmit = async () => {
  console.log(multiSelection.arr);

  userDialogVisible.value = false;

  roleUser.roleId = currentRoleId.value;
  roleUser.users = multiSelection.arr;

  let { data } = await axios.put(`UserRole/SetUsers`, roleUser);
  let { data: d, success, message } = data;

  if (!success) {
    ElMessage({
      type: 'warning',
      message: message
    });

    return;
  }

  ElMessage({
    type: 'success',
    message: '设置成功'
  });
}

//提交菜单分配
const roleMenuSubmit = async () => {
  let selectedArray = menuMultipleTableRef.value.getCheckedNodes();
  let halfSelectedArray = menuMultipleTableRef.value.getHalfCheckedNodes();

  let fullSelected = selectedArray.concat(halfSelectedArray);

  if (fullSelected.length === 0) {
    ElMessage({
      type: 'warning',
      message: '请先勾选菜单'
    });

    return;
  }

  let { data } = await axios.put(`Role/SetRoleMenus`, { roleId: assignMenuRoleId.value, menus: fullSelected });
  let { success, message } = data;

  if (!success) {
    ElMessage({
      type: 'warning',
      message: message
    });

    return;
  }

  ElMessage({
    type: 'success',
    message: '设置成功'
  });

  menuDialogVisible.value = false
}

//取消用户选择
const userRoleCancel = async () => {
  multipleTableRef.value.clearSelection();
  userListQuery.searchString = '';

  userDialogVisible.value = false;
}
//取消菜单选择
const roleMenuCancel = async () => {
  menuDialogVisible.value = false;
}

//用户选择
const handleSelectionChange = (val) => {
  if (val.length === 0) {
    return;
  }

  multiSelection.arr = val;
}

//菜单选择
const handleCheckChange = (data, checked) => {
  /* if (checked === true) {
    checkedArray.push(data);
  } else {
    if (checkedArray.filter(c => c.id === data.id).length === 0) {
      return;
    }

    let menu = checkedArray.filter(c => c.id === data.id)[0];
    checkedArray.splice(menu, '');
  } */
}

//切换页大小
const userHandleSizeChange = (val) => {
  userListQuery.pageSize = val;
  AssignRole();
}

//翻页
const userHandleCurrentChange = (val) => {
  userListQuery.pageIndex = val;
  AssignRole();
}

//分配菜单
const AssignMenu = async (id) => {
  assignMenuRoleId.value = id;
  selectTreeArray.value = [];
  dataTreeList.value = [];

  let { data } = await axios.get(`/Role/GetAllMenuTreeList/${id}`);
  let { data: d, success, message, otherSource } = data;

  if (!success) {
    ElMessage({
      type: 'warning',
      message: message,
      icon: markRaw('Warning')
    });

    return;
  }

  dataTreeList.value = d;
  menuTotalCount.value = d.length;
  selectTreeArray.value = otherSource;

  menuDialogVisible.value = true;
}

const isValueExists = (item) => {
  var arr = btnArray.value.filter(b => b.btnValue === item);

  return arr.length > 0;
}

//#endregion
</script>